package g11.testdao;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import g11.actionutil.PatientUtil;
import g11.actionutil.PatientUtilImpl;
import g11.dao.EmployeeDAO;
import g11.dao.EmployeeDAOImpl;
import g11.dao.PatientAssignmentDAO;
import g11.dao.PatientAssignmentDAOImpl;
import g11.dao.PatientDAO;
import g11.dao.PatientDAOImpl;
import g11.model.Employee;
import g11.model.Patient;
import g11.model.PatientAssignment;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.junit.Test;

public class testPatientAssignmentDao {

	private final Logger log = Logger.getLogger(this.getClass());

	@Test
	public void test() throws Exception {
		// fail("Not yet implemented");
		// create a patient first
		Patient patient = new Patient();
		patient.setUsername("jhope");
		patient.setName("Julia Hope");
		patient.setPassword("1234");
		Byte type = 0;
		patient.setType(type);
		patient.setPhone("519-888-8888");
		patient.setAddress("77 Weber Street");
		patient.setOhip("2222222222ka");
		patient.setSin("1111111111");
		patient.setCurrentHealth("Diabetes.");
		Date date = new Date();
		java.sql.Date myDate = new java.sql.Date(date.getTime());
		patient.setLastVisitTime(myDate);
		log.info(myDate.toString());
		// patient.setDepartment("Surgery");
		// patient.setTitle("Surgery Doctor");
		// create start
		PatientDAO patientDao = new PatientDAOImpl();
		patientDao.createPatient(patient);
		Patient retrievedPatient = new Patient();
		retrievedPatient = patientDao.getPatientByOhip(patient.getOhip());
		// create a doctor
		Employee employee = new Employee();
		employee.setUsername("pmoney");
		employee.setPassword("1234");
		Byte doctype = 1;
		employee.setType(doctype);
		employee.setName("Penny Money");
		employee.setDepartment("Surgery");
		employee.setTitle("Surgery Doctor");
		// create start
		EmployeeDAO employeeDao = new EmployeeDAOImpl();
		employeeDao.createEmployee(employee);
		Employee retrievedEmployee = employeeDao.getEmployeeByUsername(employee
				.getUsername());

		/*
		 * assign this patient and doctor to default doctor relationship
		 * PatientAssignment pAssign = new PatientAssignment();
		 * pAssign.setDoctorId(employee.getId());
		 * pAssign.setPatientId(patient.getId()); byte permission =0;
		 * pAssign.setPermission(permission);
		 */
		log.info("assign this patientn to this doctor");
		byte permission = 0;
		PatientAssignmentDAO pAssignDao = new PatientAssignmentDAOImpl();
		pAssignDao.CreatePatientAssignment(employee, patient, permission);

		// get permission
		log.info("get permission from the DAO");
		byte rePermission = pAssignDao.getPermission(employee, patient);
		assertEquals(permission, rePermission);
		// test retrive
		PatientAssignment retrievedPatientAssignment = new PatientAssignment();
		retrievedPatientAssignment = (PatientAssignment) pAssignDao
				.getPatientAssignmentByDoctorAndPermission(retrievedEmployee,
						rePermission).get(0);
		assertEquals((int) retrievedPatientAssignment.getDoctorId(),
				(int) retrievedEmployee.getId());
		assertEquals((int) retrievedPatientAssignment.getPatientId(),
				(int) retrievedPatient.getId());
		assertEquals(retrievedPatientAssignment.getPermission(), rePermission);

		// below are testing methods from PatientUtil; create two more Employees
		// and one more patient first
		// create a doctor
		log.info("Create the second employee: Tom Hanks");
		Employee employee1 = new Employee();
		employee1.setUsername("THanks");
		employee1.setPassword("1234");
		doctype = 1;
		employee1.setType(doctype);
		employee1.setName("Tom Hanks");
		employee1.setDepartment("Surgery");
		employee1.setTitle("Surgery Doctor");
		employeeDao.createEmployee(employee1);

		log.info("Create the third employee: Will Woods");
		Employee employee2 = new Employee();
		employee2.setUsername("wwoods");
		employee2.setPassword("1234");
		doctype = 1;
		employee2.setType(doctype);
		employee2.setName("Will Woods");
		employee2.setDepartment("Surgery");
		employee2.setTitle("Surgery Doctor");
		employeeDao.createEmployee(employee2);

		log.info("Create the second patient: Julia Roberts");
		Patient patient1 = new Patient();
		patient1.setUsername("jroberts");
		patient1.setName("julia Roberts");
		patient1.setPassword("1234");
		type = 0;
		patient1.setType(type);
		patient1.setPhone("519-888-8888");
		patient1.setAddress("77 Weber Street");
		patient1.setOhip("3333222222ka");
		patient1.setSin("2222111111");
		patient1.setCurrentHealth("Diabetes.");
		patient1.setLastVisitTime(myDate);
		patientDao.createPatient(patient1);

		// assign patient to employee1 with read only type
		log.info("assign patient to employee1 with readonly type");
		permission = 1;
		// PatientAssignmentDAO pAssignDao1 = new PatientAssignmentDAOImpl();
		pAssignDao.CreatePatientAssignment(employee1, patient, permission);

		// assign patient1 to employee1 with default type
		log.info("assign patient1 to employee1 with default type");
		permission = 0;
		pAssignDao.CreatePatientAssignment(employee1, patient1, permission);

		List<Patient> patientList = new ArrayList<Patient>();
		log.info("test pAssignDao.getPatientByDoctorBelongTo(employee1) ");
		patientList = pAssignDao.getPatientByDoctorBelongTo(employee1);
		log.info("to check if pAssignDao.getPatientByDoctorBelongTo(employee1) equals patient ");
		assertEquals(patientList.get(0).getId(), patient1.getId());

		log.info("test pAssignDao.getPatientByDoctorReadOnly(employee1) ");
		patientList = pAssignDao.getPatientByDoctorReadOnly(employee1);
		log.info("to check if pAssignDao.getPatientByDoctorReadOnly(employee1) equals patient ");
		assertEquals(patientList.get(0).getId(), patient.getId());

		log.info("test pAssignDao.getAllPatient(employee1) ");
		patientList = pAssignDao.getAllPatient(employee1);
		// should return patient and patient1
		assertEquals(patientList.get(0).getId(), patient.getId());
		assertEquals(patientList.get(1).getId(), patient1.getId());

		// test getPatientByKeywordForDoctor(Employee doctor,String patientName)
		log.info("test getPatientByKeywordForDoctor(Employee doctor,String patientName) ");
		patientList = pAssignDao.searchBelongToPatientForDoctor(
				String.valueOf(employee1.getId()), 0, "Julia");
		log.info("to check if pAssignDao.getPatientByKeywordForDoctor(employee1) equals two patients whose names like Julia ");
		assertEquals(patientList.get(0).getId(), patient1.getId());
		// assertEquals(patientList.get(0).getId(),patient1.getId());

		// test to revoke patient from employee1 the read only permission
		log.info("test revokePatientToDoctor(Patient patient, Employee doctor)");
		PatientUtil pu = new PatientUtilImpl();
		assertTrue(pu.revokePatientToDoctor(patient, employee1));
		// patient1 has no relationship to employee2
		assertFalse(pu.revokePatientToDoctor(patient1, employee2));
		// patient1 has default to relationship to employee1, so still cann't
		// revoke
		assertFalse(pu.revokePatientToDoctor(patient1, employee1));

		// assign patient to employee1 with read only type again
		permission = 1;
		// PatientAssignmentDAO pAssignDao1 = new PatientAssignmentDAOImpl();
		pAssignDao.CreatePatientAssignment(employee1, patient, permission);

		// create a staff in the Employee table to test
		// getAllNotAssignedDoctorListForPatient( patient)
		Employee employee3 = new Employee();
		employee3.setUsername("hyoung");
		employee3.setPassword("1234");
		byte staffType = 2;
		employee3.setType(staffType);
		employee3.setName("Henry Young");
		employee3.setDepartment("Nurse");
		employee3.setTitle("PR");
		employeeDao.createEmployee(employee3);

		// test List<Employee> getAllNotAssignedDoctorListForPatient(Patient
		// patient)
		log.info("test getAllNotAssignedDoctorListForPatient( patient)");
		List<Employee> docList = new ArrayList<Employee>();
		docList = pAssignDao.getAllNotAssignedDoctorListForPatient(patient);
		/*
		 * patient has been assigned to employee with default type and to
		 * employee1 with read only type; patient1 has been assigned to
		 * employee1 with default type.so for patient it should return
		 * employee2, for patient1 it should return employee and employee2
		 */
		assertEquals(docList.get(0).getId(), employee2.getId());
		log.info("test getAllNotAssignedDoctorListForPatient( patient1)");
		docList = pAssignDao.getAllNotAssignedDoctorListForPatient(patient1);
		assertEquals(docList.get(0).getId(), employee.getId());
		assertEquals(docList.get(1).getId(), employee2.getId());

		// test PatientUtilImpl:assignPatientToDoctor(Patient patient, Employee
		// doctor, byte permission)
		// PatientUtil pu=new PatientUtilImpl();
		byte prms = 0;
		// first test a already default type
		assertFalse(pu.assignPatientToDoctor(patient1, employee1, prms));
		// then test a already ready only type
		prms = 1;
		assertFalse(pu.assignPatientToDoctor(patient, employee1, prms));

		// at last, a non-exist type
		prms = 1;
		assertTrue(pu.assignPatientToDoctor(patient1, employee2, prms));

		// delete
		log.info("delete all relationships and all entities");
		pAssignDao.DeletePatientAssignment(employee, patient);
		pAssignDao.DeletePatientAssignment(employee1, patient);
		pAssignDao.DeletePatientAssignment(employee1, patient1);
		pAssignDao.DeletePatientAssignment(employee2, patient1);
		employeeDao.deleteEmployee(retrievedEmployee);
		employeeDao.deleteEmployee(employee1);
		employeeDao.deleteEmployee(employee2);
		employeeDao.deleteEmployee(employee3);
		patientDao.deletePatient(retrievedPatient);
		patientDao.deletePatient(patient1);
	}

}
